/**
 * 
 */
package neptune.web.client;

import neptune.web.client.controller.HistoryController;
import neptune.web.client.controller.LogInController;
import neptune.web.client.model.DefaultRoles;
import neptune.web.client.services.ApplicationDataProvider;
import neptune.web.client.services.ClusterDataProvider;
import neptune.web.client.view.ClusterView;
import neptune.web.client.view.ConsoleManager;
import neptune.web.client.view.ExperimentSummaryView;
import neptune.web.client.view.ExperimentView;
import neptune.web.client.view.HistoryTokenUtils;
import neptune.web.client.view.LogInView;
import neptune.web.client.view.OperativeView;
import neptune.web.client.view.PerformanceView;
import neptune.web.client.view.SuperView;
import neptune.web.client.view.TaskView;
import neptune.web.client.view.TemplatesSummaryView;
import neptune.web.client.view.UserView;
import neptune.web.client.view.ViewManager;
import neptune.web.client.view.components.AdminMenuBar;

import org.gwt.mosaic.ui.client.Caption;
import org.gwt.mosaic.ui.client.DecoratedLayoutPopupPanel;
import org.gwt.mosaic.ui.client.ImageButton;
import org.gwt.mosaic.ui.client.MessageBox;
import org.gwt.mosaic.ui.client.WindowPanel;
import org.gwt.mosaic.ui.client.Caption.CaptionRegion;
import org.gwt.mosaic.ui.client.WindowPanel.WindowState;
import org.gwt.mosaic.ui.client.WindowPanel.WindowStateListener;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Entry point dell'applicazione client, contiene anche metodi di utilita' varia
 * per il client
 * 
 * @author Roberto Bifulco [info@robertobifulco.it, robertobifulco.it]
 * 
 */
public class WebInterface implements EntryPoint {

	public void onModuleLoad() {
		// Elimina il pannello di caricamento iniziale
		RootPanel.get("preloading").setVisible(false);

		startClientApplication();
	}

	/**
	 * Metodo chiamato all'avvio dell'applicazione per l'inizializzazione di
	 * tutte le componenti.
	 */
	private void startClientApplication() {

		// Ottiene il gestore delle view che e' creato al caricamento
		// dell'applicazione, prima della chiamata di questo meotodo
		ViewManager viewManager = ViewManager.getViewManager();

		/*
		 * Creazione delle view
		 */
		// LOGIN VIEW
		LogInView login = new LogInView();
		login.setListener(new LogInController());

		// OPERATIVE VIEW
		// Inizialmente viene definita l'admin menu bar per l'operative view, in
		// realta', non e' una indicazione importante, poiche' a login avvenuto,
		// verra' impostata la menuBar opportuna.
		OperativeView operative = new OperativeView(new AdminMenuBar());

		// Registering consoles
		/*
		 * La registrazione delle console permette di avere nel ConsoleManager
		 * un punto di accesso centrale per l'invio di messaggi all'utente.
		 */
		ConsoleManager.addConsole(login);
		ConsoleManager.addConsole(operative);

		// Registrazione delle view al viewManager
		viewManager.addView(login);
		viewManager.addView(operative);
		/*
		 * fine creazione view
		 */

		// La view attiva all'avvio dell'applicazione deve essere la LogInView
		// TODO valutare la possibilita' di selezionare la view in base
		// all'eventuale token presente nell'history
		viewManager.setActiveView(LogInView.DEFAULT_TOKEN);
		// Aggiunge l'historyController per gestire i token definiti dalle view
		History.addHistoryListener(new HistoryController());

		// Include il viewManager nella pagina html
		RootPanel.get("wrapper").add(viewManager);
	}

	/**
	 * Metodo di che viene adoperato per aggiornare tutte le view definite per
	 * l'OperativeView. L'aggiornamento prevede tanto la creazione quanto
	 * l'eliminazione delle view in base all'attuale ruolo ricoperto
	 * dall'utente.
	 */
	public static void updateViewsOfOperativeView() {
		// Recupera l'operativeView
		SuperView operative = (SuperView) ViewManager.getViewManager()
				.getViewByName(OperativeView.DEFAULT_TOKEN);

		// Se l'Utente e' system admin: Aggiunge, se non e' gia' presente, la
		// userView, clusterView e la performanceView alla operativeView
		if (ApplicationDataProvider.getInstance().getActualUserRole().equals(
				DefaultRoles.SYSTEM_ADMIN)) {

			if (operative.getViewByName(UserView.DEFAULT_TOKEN) == null) {
				HistoryTokenUtils.unregisterViewToken(UserView.DEFAULT_TOKEN);
				UserView usrView = new UserView();
				operative.addView(usrView);
			}

			if (operative.getViewByName(ClusterView.DEFAULT_TOKEN) == null) {
				HistoryTokenUtils
						.unregisterViewToken(ClusterView.DEFAULT_TOKEN);
				ClusterView clusterView = new ClusterView();
				clusterView.setDataProvider(new ClusterDataProvider());
				operative.addView(clusterView);
			}

			if (operative.getViewByName(PerformanceView.DEFAULT_TOKEN) == null) {
				HistoryTokenUtils
						.unregisterViewToken(PerformanceView.DEFAULT_TOKEN);
				PerformanceView performanceView = new PerformanceView();
				// clusterView.setDataProvider(new ClusterDataProvider());
				operative.addView(performanceView);
			}

			if (operative.getViewByName(TaskView.DEFAULT_TOKEN) == null) {
				HistoryTokenUtils.unregisterViewToken(TaskView.DEFAULT_TOKEN);
				TaskView taskView = new TaskView();
				operative.addView(taskView);
			}

			if (operative.getViewByName(TemplatesSummaryView.DEFAULT_TOKEN) == null) {
				HistoryTokenUtils
						.unregisterViewToken(TemplatesSummaryView.DEFAULT_TOKEN);
				TemplatesSummaryView templatesView = new TemplatesSummaryView();
				operative.addView(templatesView);
			}
		}

		// Se l'Utente e' user: Elimina, se e' presente, la
		// userView dalla operativeView
		if (!ApplicationDataProvider.getInstance().getActualUserRole().equals(
				DefaultRoles.SYSTEM_ADMIN)) {
			operative.removeView(UserView.DEFAULT_TOKEN);
		}

		if (operative.getViewByName(ExperimentSummaryView.DEFAULT_TOKEN) == null) {
			ExperimentSummaryView expSumView = new ExperimentSummaryView();
			operative.addView(expSumView);
		}

		if (operative.getViewByName(ExperimentView.DEFAULT_TOKEN) == null) {
			ExperimentView expView = new ExperimentView();
			operative.addView(expView);
		}
	}

	/**
	 * Mostra una message dialog con il messaggio rappresentato da un
	 * MessageWidget. La dialog puo' essere sia impostata come AutoHide, nel
	 * qual caso scomparira' quando si clicca al di fuori di essa, oppure puo'
	 * essere fatta scomparire manualmente. Per questa ragione, il metodo
	 * restituisce un riferimento alla dialog creata. s
	 * 
	 * @param message
	 * @param autohide
	 * @return
	 */
	public static PopupPanel showMessageDialog(Widget message, boolean autohide) {
		DecoratedLayoutPopupPanel popup = new DecoratedLayoutPopupPanel(
				autohide, true);
		popup.add(message);
		popup.setAnimationEnabled(true);
		popup.pack();
		popup.center();

		return popup;
	}

	public static void showMessageWindow(Widget message, String caption,
			int width, int height) {
		WindowPanel window = new WindowPanel();
		window.setCaption(caption);
		window.setWidget(message);
		window.setPixelSize(width, height);
		window.setAnimationEnabled(true);
		window.setResizable(false);

		addMaximizeButton(window, CaptionRegion.RIGHT);
		addMinimizeButton(window, CaptionRegion.RIGHT);

		window.pack();
		window.center();
	}

	/**
	 * Metodo di utilita' per aggiungere un messaggio al console manager ed allo
	 * stesso tempo mostrare una dialog con l'opzione di AutoHide che conterra'
	 * lo stesso messaggio.
	 * 
	 * @param message
	 * @param error
	 */
	public static void addMessageToConsoleAndShowDialog(String message,
			boolean error) {
		ConsoleManager.addConsoleMessage(message, error);
		if (error)
			MessageBox.error("Error", message);
		else
			MessageBox.info("Info", message);
	}

	/*
	 * ==================================================================
	 * Utility methods fow WindowPanel ==================================
	 * ==================================================================
	 */

	private static void addMaximizeButton(final WindowPanel windowPanel,
			CaptionRegion captionRegion) {
		final ImageButton maximizeBtn = new ImageButton(Caption.IMAGES
				.windowMaximize());
		maximizeBtn.addClickListener(new ClickListener() {
			public void onClick(Widget sender) {
				if (windowPanel.getWindowState() == WindowState.MAXIMIZED) {
					windowPanel.setWindowState(WindowState.NORMAL);
				} else {
					windowPanel.setWindowState(WindowState.MAXIMIZED);
				}
			}
		});
		windowPanel.addWindowStateListener(new WindowStateListener() {
			public void onWindowStateChange(WindowPanel sender) {
				if (sender.getWindowState() == WindowState.MAXIMIZED) {
					maximizeBtn.setImage(Caption.IMAGES.windowRestore()
							.createImage());
				} else {
					maximizeBtn.setImage(Caption.IMAGES.windowMaximize()
							.createImage());
				}

			}
		});
		windowPanel.getHeader().add(maximizeBtn, captionRegion);
	}

	/*
	 * 
	 * @param windowPanel
	 */
	private static void addMinimizeButton(final WindowPanel windowPanel,
			CaptionRegion captionRegion) {
		final ImageButton minimizeBtn = new ImageButton(Caption.IMAGES
				.windowMinimize());
		minimizeBtn.addClickListener(new ClickListener() {
			public void onClick(Widget sender) {
				windowPanel.setWindowState(WindowState.MINIMIZED);
			}
		});
		windowPanel.getHeader().add(minimizeBtn, captionRegion);
	}

	/*
	 * ==================================================================
	 * ==================================================================
	 * ==================================================================
	 */
}
